package com.dcy.znoa.service.attendance.impl;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.dcy.znoa.common.enums.PushBusinessCode;
import com.dcy.znoa.common.exception.BusinessException;
import com.dcy.znoa.common.util.DateTimeUtil;
import com.dcy.znoa.common.util.DateUtil;
import com.dcy.znoa.common.util.JpushUtils;
import com.dcy.znoa.common.util.ZnoaConstant;
import com.dcy.znoa.common.util.pojo.JsonForList;
import com.dcy.znoa.controller.attendance.model.apply.*;
import com.dcy.znoa.controller.publiz.model.messNotice.AddMessNoticeListAndMsgModel;
import com.dcy.znoa.controller.sys.model.storeFile.AddStoreFileModel;
import com.dcy.znoa.dao.attendance.ApplyDao;
import com.dcy.znoa.dao.attendance.AttRealRecordDao;
import com.dcy.znoa.dao.attendance.AttRecordDao;
import com.dcy.znoa.dao.publiz.CompanyDao;
import com.dcy.znoa.dao.publiz.MessNoticeDao;
import com.dcy.znoa.dao.publiz.MessageDao;
import com.dcy.znoa.dao.user.OperDao;
import com.dcy.znoa.domain.Oper;
import com.dcy.znoa.domain.attendance.Apply;
import com.dcy.znoa.domain.attendance.AttRealRecord;
import com.dcy.znoa.domain.attendance.AttRecord;
import com.dcy.znoa.domain.attendance.AttRule;
import com.dcy.znoa.domain.publiz.Company;
import com.dcy.znoa.domain.publiz.Message;
import com.dcy.znoa.domain.sys.StoreFile;
import com.dcy.znoa.service.attendance.ApplyService;
import com.dcy.znoa.service.attendance.AttRuleService;
import com.dcy.znoa.service.publiz.MessNoticeService;
import com.dcy.znoa.service.sys.StoreFileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class ApplyServiceImpl implements ApplyService {
    @Autowired
    ApplyDao applyDao;
    @Autowired
    OperDao operDao;
    @Autowired
    MessageDao messageDao;
    @Autowired
    MessNoticeDao messNoticeDao;
    @Autowired
    StoreFileService storeFileService;
    @Autowired
    MessNoticeService messNoticeService;
    @Resource
    AttRuleService attRuleService;
    @Resource
    AttRecordDao attRecordDao;
    @Resource
    AttRealRecordDao attRealRecordDao;

    @Override
    public JsonForList selectList(SelectApplyModel model) throws InvocationTargetException, IllegalAccessException {
        Page page = new Page(model.getPageNum(), model.getPageSize());
        if(StringUtils.isBlank(model.getSt())){
            model.setSt(null);
        }
        if(StringUtils.isBlank(model.getEt())){
            model.setEt(null);
        }
        List list = applyDao.selectListMapper(model, page);
        return new JsonForList(list, page.getTotal());
    }

    @Transactional
    @Override
    public Apply add(AddApplyModel model) throws InvocationTargetException, IllegalAccessException, BusinessException, ClientException {
        if(model.getStartTime()==null || model.getEndTime()==null){
            throw new BusinessException("404","开始时间和结束时间不能为空");
        }
        Date now = new Date();
        //申请的消息：申请类型 1 请假 2 出差 3 外勤  是一类 9 申述 是一类，申述需要有对应的考勤记录
        Integer type = model.getType();
        switch (type) {
            case 1:
            case 2:
            case 3:
                String title = model.getTitle();
                if (StringUtils.isBlank(title)) {
                    throw new BusinessException("404", "申请时，标题不能为空");
                }
                break;
            case 9:
                Long eId = model.getEId();
                String eName = model.getEName();
                log.info("eId = " + eId + "eName =" + eName);
                if (eId == null || StringUtils.isBlank(eName) || !eName.equals("att_real_record")) {
                    throw new BusinessException("404", "申述时，请检查eName和eId");
                }
                break;
            default:
                throw new BusinessException("404", "申请类型有误");
        }
        Apply cp = new Apply();
        BeanUtils.copyProperties(cp, model);
        applyDao.insert(cp);
        //消息表
//        Message message = new Message();
//        BeanUtils.copyProperties(message, model);
//        message.setCreateOperId(model.getSendOperId());
//        message.setCreateTime(now);
//        messageDao.insert(message);
//        Long messId = message.getMessId();
//        if(messId==null){
//            throw new BusinessException("404","新增消息（公告）失败");
//        }
        //消息表  消息用户关联表  要把审核人放进去 + 极光 + 短信
//        MessNotice messNotice = new MessNotice();
//        BeanUtils.copyProperties(messNotice, model);
//        messNotice.setMessId(messId);
        AddMessNoticeListAndMsgModel amnlModel = new AddMessNoticeListAndMsgModel();
        BeanUtils.copyProperties(amnlModel, model);
        amnlModel.setCreateOperId(model.getSendOperId());
        amnlModel.setOperIdsStr(String.valueOf(model.getReceiveOperId()));
//        amnlModel.setMessEntityId(cp.getApplyId());
//        amnlModel.setMessEntityTbl("apply");
        amnlModel.setEntityId(cp.getApplyId());
        amnlModel.setEntityTbl("apply");
        amnlModel.setMessType(2);//不会有3
        amnlModel.setMessTitle(model.getTitle());
//        amnlModel.setMessage(model.getMessage());
        amnlModel.setMessage(model.getContent());
        //给接收人的消息
        Long messId = messNoticeService.insertBatchAndMsg(amnlModel);

        //附件表
//        AddStoreFileModel addStoreFileModel = new AddStoreFileModel();
//        BeanUtils.copyProperties(addStoreFileModel, model);
//        addStoreFileModel.setEntityId(messId);
//        addStoreFileModel.setEntityTbl(StoreFile.ENTITY_MSG);
//        if(model.getRemoteFileName()!=null && model.getFileName()!=null){
//            String[] fileNames = model.getRemoteFileName().split("\\,");
//            for (String remoteFileName : fileNames) {
//                StoreFile storeFile = new StoreFile();
//                BeanUtils.copyProperties(storeFile, addStoreFileModel);
//                storeFile.setRemoteFileName(remoteFileName);
//                storeFileService.insert(storeFile);
//            }
//        }
        return cp;

    }
    @Transactional
    @Override
    public Integer revoke(RevokeApplyModel model) throws BusinessException, InvocationTargetException, IllegalAccessException {
        //查看是不是已经被审核
        Date now = new Date();
        Long applyId = model.getApplyId();
        Apply apply = applyDao.selectById(applyId);
        if (apply == null) {
            throw new BusinessException("404", "该申请不存在");
        }
        Integer isAudit = apply.getIsAudit();
        if (isAudit != null && isAudit > 0) {
            throw new BusinessException("404", "该申请已经被审核");
        }
        BeanUtils.copyProperties(apply, model);
        applyDao.updateById(apply);
        //给申请人发消息
        Long operId = apply.getSendOperId();
        if (operId == null) {
            throw new BusinessException("404", "该申请相关用户不存在，请联系管理员");
        }
        Integer type = apply.getType();
        String typeStr = "申请";
        if (type != null && type == 9) {
            typeStr = "申述";
        }
        Oper oper = operDao.selectById(operId);
        String msgMsg = "";
        String msgTitle = "";
        if (oper != null && oper.getPushId() != null) {
            if (isAudit == null) {
                isAudit = 0;
            }
            switch (isAudit) {
                case 0:
                    msgTitle = "未审核";
                    msgMsg = typeStr + msgTitle;
                    break;
                case 1:
                    msgTitle = "已通过";
                    msgMsg = typeStr + msgTitle;
                    break;
                case 2:
                    msgTitle = "未通过";
                    msgMsg = typeStr + msgTitle + " : " + apply.getAuditContent();
                    break;
            }
            Long entityId = null;
            String entityTbl = null;
            if(apply.getType() == null ){
                throw  new BusinessException("404","申请类型不存在的异常");
            }
            if(apply.getType()== 9){
                entityId = apply.getEId();
                entityTbl = apply.getEName();
            }else{
                entityId = apply.getApplyId();
                entityTbl = "apply";
            }
            Message message = new Message(entityId ,entityTbl ,apply.getTitle() + " " + msgTitle, msgMsg, 2, 0, now, operId, now, 1);
            Map<String, String> pushMap = new HashMap<>();
            pushMap.put(PushBusinessCode.ACTION, PushBusinessCode.NOTICE.getCode());
            pushMap.put(PushBusinessCode.DATA, JSON.toJSONString(message));
            JpushUtils.pushMsgByRegId(oper.getPushId(), pushMap);
        }
        return 1;
    }

    //申请只能对今天以后；申述只能对今天之前
    @Transactional
    @Override
    public Integer audit(AuditApplyModel model) throws BusinessException, InvocationTargetException, IllegalAccessException, ParseException {
        //查看是不是已经被审核
        Date now = new Date();
        Long applyId = model.getApplyId();
        Apply apply = applyDao.selectById(applyId);
        Integer type = apply.getType();
        if (type == null) {
            throw new BusinessException("404", "该申请类型有误：" + type);
        }
        if (apply == null) {
            throw new BusinessException("404", "该申请不存在");
        }
        Integer isAudit = apply.getIsAudit();
        if (isAudit != null && isAudit > 0) {
            throw new BusinessException("404", "该申请已经被审核");
        }
        Integer isRevoke = apply.getIsRevoke();
        if (isRevoke != null && isRevoke == 1) {
            throw new BusinessException("404", "该申请已经被撤回");
        }
//        apply.setIsRevoke(1);
        BeanUtils.copyProperties(apply, model);
        Integer result = applyDao.updateById(apply);
        //给自己发消息
        Long operId = apply.getSendOperId();
        if (operId == null) {
            throw new BusinessException("404", "该申请相关用户不存在，请联系管理员");
        }
        Oper oper = operDao.selectById(operId);
        //如果申请已经被审核成功，那么对应的考勤记录全部要改成已申请
        Integer isAuditNew = model.getIsAudit();
        if(type!=9) {//申请
            if (isAuditNew != null && isAuditNew == 1 && result > 0) {
                //格式化为string 来比较  或 datetimeFormat 去掉年月日后 来比较
                Date appST = apply.getStartTime();
//            Date appStHMS = DateTimeUtil.getHMSDate(appST);
                Date appStYMR = DateTimeUtil.getYMRDate(appST);
                Date appET = apply.getEndTime();
                Date appEtHMS = DateTimeUtil.getHMSDate(appET);
                //查询这人的考勤规则，开始时间和结束时间
                AttRule attRule = attRuleService.queryByOperId(operId);
                Date ruleST = attRule.getStartTime();
                Date ruleET = attRule.getEndTime();
                String ruleEtHMSStr = DateTimeUtil.datetimeFormat_HMS.format(ruleET);
                //XXX 目前粗暴认为申请的全天都是申请，不用考勤
                String appStYMRStr = DateTimeUtil.dateFormat.format(appStYMR);
                //申请当天的上班规定时间为
                String ruleStHMsStr = DateTimeUtil.datetimeFormat_HMS.format(ruleST);
                Date ruleStYMRHMS = DateTimeUtil.datetimeFormat.parse(appStYMRStr + " " + ruleStHMsStr);
                //申请当天的下班规定时间为
                String ruleEtHMsStr = DateTimeUtil.datetimeFormat_HMS.format(ruleET);
                Date ruleEtYMRHMS = DateTimeUtil.datetimeFormat.parse(appStYMRStr + " " + ruleEtHMsStr);

                Date appStTemp = apply.getStartTime();
                Date appEtTemp = DateTimeUtil.datetimeFormat.parse(appStYMRStr + " " + ruleEtHMSStr);
                Date attTimeTemp = DateTimeUtil.dateFormat.parse(appStYMRStr);
                boolean flag = false;
                while (flag == false) {
                    if (appStTemp.after(appET)) {
                        break;
                    }
                    if (!appStTemp.after(ruleStYMRHMS)) {//若要校验Date2必须比Date1小，且不能相等时，使用 !Date1.after(Date2)
                        // 上班的考勤记录

                        AttRecord attRecord = new AttRecord(operId, oper.getCompId(), 1, 1, 1, attTimeTemp);
                        attRecordDao.insert(attRecord);
                        AttRealRecord cpr = new AttRealRecord();
                        BeanUtils.copyProperties(cpr, attRecord);
                        if (type == 9) { //delete then insert,else insert
                            attRealRecordDao.delete(new EntityWrapper<AttRealRecord>().eq(("oper_id"), operId).eq("record_type", 1).eq("att_time", attTimeTemp));
                        }
                        attRealRecordDao.insert(cpr);
                    }
                    if (appEtTemp.after(appET)) {
                        break;
                    }
                    if (!appEtTemp.before(ruleEtYMRHMS)) {
                        // 下班的考勤记录
                        AttRecord attRecord = new AttRecord(operId, oper.getCompId(), 2, 1, 1, attTimeTemp);
                        attRecordDao.insert(attRecord);
                        AttRealRecord cpr = new AttRealRecord();
                        BeanUtils.copyProperties(cpr, attRecord);
                        if (type == 9) { //delete then insert,else insert
                            attRealRecordDao.delete(new EntityWrapper<AttRealRecord>().eq(("oper_id"), operId).eq("record_type", 2).eq("att_time", attTimeTemp));
                        }
                        attRealRecordDao.insert(cpr);
                    }
                    appStTemp = DateTimeUtil.addDay(appStTemp, 1);
                    appEtTemp = DateTimeUtil.addDay(appEtTemp, 1);
                    ruleStYMRHMS = DateTimeUtil.addDay(ruleStYMRHMS, 1);
                    ruleEtYMRHMS = DateTimeUtil.addDay(ruleEtYMRHMS, 1);
                    attTimeTemp = DateTimeUtil.addDay(attTimeTemp, 1);
                }

//            // update att_record 和 att_real_record
//            int days = DateTimeUtil.differentDaysByMillisecond(appST,appET);
//            if(days<=0){
//                if(appStHMS.before(ruleST)) {
//                    // 上班的考勤记录
//                }
//                if(){}
//            }else{
//                for(int i =0;i<days;i++){
//
//                }
//            }
//
//            boolean flag = false;
//            while(flag==false){
//            //
//                if(appStHMS.before(ruleST)){
//                    // 上班的考勤记录
//
//                    // 上班的考勤记录
//                }
//
//            }
//
//        }


                if (oper != null && oper.getPushId() != null) {
                    Long entityId = null;
                    String entityTbl = null;
                    if(apply.getType()== 9){
//                        entityId = apply.getEId();
//                        entityTbl = apply.getEName();
                        entityId = apply.getApplyId();
                        entityTbl = "apply";
                    }else{
                        entityId = apply.getApplyId();
                        entityTbl = "apply";
                    }
                    Message message = new Message(entityId , entityTbl , apply.getTitle() + " 申请已审核", null, 2, 0, now, operId, now, 1);
                    Map<String, String> pushMap = new HashMap<>();
                    pushMap.put(PushBusinessCode.ACTION, PushBusinessCode.NOTICE.getCode());
                    pushMap.put(PushBusinessCode.DATA, JSON.toJSONString(message));
                    JpushUtils.pushMsgByRegId(oper.getPushId(), pushMap);
                }
            }
        }else{//申述
            if (isAuditNew != null && isAuditNew == 1 && result > 0) {
                AttRealRecord attRealRecord = attRealRecordDao.selectById(apply.getEId());
                if (attRealRecord == null) {
                    throw new BusinessException("404", "EId不存在");
                }
                //pengyu add 20180718 考虑 attRealRecord 表中是否加一个字段来表示是否正常
                attRealRecord.setAddStatus(1);
                attRealRecord.setTimeStatus(1);
                attRealRecord.setRemark("已通过申述审核");
                attRealRecordDao.updateById(attRealRecord);

                if (oper != null && oper.getPushId() != null) {
                    if(apply.getType() == null ){
                        throw  new BusinessException("404","申请类型不存在的异常");
                    }
                    Long entityId = null;
                    String entityTbl = null;
                    if(apply.getType()== 9){
//                        entityId = apply.getEId();
//                        entityTbl = apply.getEName();
                        entityId = apply.getApplyId();
                        entityTbl = "apply";
                    }else{
                        entityId = apply.getApplyId();
                        entityTbl = "apply";
                    }
                    Message message = new Message(entityId,entityTbl,apply.getTitle() + " 申述已审核", null, 2, 0, now, operId, now, 1);
                    Map<String, String> pushMap = new HashMap<>();
                    pushMap.put(PushBusinessCode.ACTION, PushBusinessCode.NOTICE.getCode());
                    pushMap.put(PushBusinessCode.DATA, JSON.toJSONString(message));
                    JpushUtils.pushMsgByRegId(oper.getPushId(), pushMap);
                }
            }
        }
        return 1;
    }

    @Override
    public List queryDetail(Long applyId) {
        return storeFileService.selectStoreFileByEntityId(applyId, ZnoaConstant.TABLE_APPLY, null);
    }

    @Override
    public JsonForList queryReasonList(SelectApplyModel model) {
        Page page = new Page(model.getPageNum(), model.getPageSize());
        List list = applyDao.queryReasonList(model, page);
        return new JsonForList(list, page.getTotal());
    }

    @Override
    public SelectApplyNum selectSendAndReceiveNumByOperId(SendApplyModel model) {
//        List<SelectApplyNum> list = applyDao.selectSendAndReceiveNumByOperId(operId);
//        if(!list.isEmpty()){
//            return list.get(0);
//        }
        SelectApplyNum selectApplyNum = applyDao.selectSendAndReceiveNumByOperId(model);
        return selectApplyNum;
    }

    @Override
    public Apply selectById(Long applyId) {
        Apply apply = applyDao.selectById(applyId);
        List<StoreFile> list = storeFileService.selectStoreFileByEntityId(applyId, ZnoaConstant.TABLE_APPLY, null);
        apply.setStoreFileList(list);
        return apply;
    }

}
